﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Serialization;

namespace WeiXinSDK.Core
{
    public class Utility
    {
        #region

        /// <summary>
        /// 将IDataReader的数据转换为目标的实体类集合
        /// </summary>
        /// <typeparam name="T">目标的实体类型</typeparam>
        /// <param name="dr">数据源</param>
        /// <returns>目标的实体类对象集合</returns>
        public static List<T> ToList<T>(IDataReader dr) where T : new()
        {
            // 定义集合  
            List<T> ts = new List<T>();

            try
            {
                using (dr)
                {
                    //遍历IDataReader中所有的数据行  
                    if (dr != null)
                    {
                        while (dr.Read())
                        {
                            T t = newT<T>(dr);

                            //对象添加到泛型集合中  
                            ts.Add(t);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return ts;
        }

        /// <summary>
        /// 将IDataReader的数据转换为目标的实体类
        /// </summary>
        /// <typeparam name="T">目标的实体类型</typeparam>
        /// <param name="dr">数据源</param>
        /// <returns>目标的实体类对象</returns>
        public static T ToInstance<T>(IDataReader dr) where T : new()
        {
            try
            {
                using (dr)
                {
                    //遍历IDataReader中所有的数据行  
                    if (dr != null)
                    {
                        if (dr.Read())
                        {
                            return newT<T>(dr);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return default(T);
        }

        /// <summary>
        /// 将IDataReader的数据转换为目标的实体类
        /// </summary>
        /// <typeparam name="T">目标的实体类型</typeparam>
        /// <param name="dr">数据源</param>
        /// <returns>目标的实体类对象</returns>
        private static T newT<T>(IDataReader dr) where T : new()
        {
            try
            {
                T t = new T();

                // 获得此模型的所有属性  
                PropertyInfo[] properties = t.GetType().GetProperties();
                PropertyInfo prop;

                // 获得此模型的所有字段  
                FieldInfo[] fields = t.GetType().GetFields();
                FieldInfo field;

                for (int i = 0; i < dr.FieldCount; i++)
                {
                    try
                    {
                        //取值  
                        object value = dr.GetValue(i);

                        //找到字段对应的的属性  
                        if (properties.Any(p => string.Compare(p.Name, dr.GetName(i), true) == 0))
                        {
                            prop = properties.First(p => string.Compare(p.Name, dr.GetName(i), true) == 0);
                            if (!prop.CanWrite)//该属性不可写，直接跳出  
                            {
                                continue;
                            }

                            //如果非空，则赋给对象的属性  
                            if (value != DBNull.Value)
                            {
                                if (prop.PropertyType == typeof(Boolean)) //转换为布尔值
                                {
                                    prop.SetValue(t, ValueAsBoolean(value, false), null);
                                }
                                else if (prop.PropertyType.IsEnum) //转换为枚举，支持数字和文字
                                {
                                    prop.SetValue(t, Enum.Parse(prop.PropertyType, value.ToString(), true), null);
                                }
                                else if (prop.PropertyType.Equals(typeof(DateTime)))
                                {
                                    DateTime time;
                                    TryParseDateTime(value.ToString(), out time);
                                    prop.SetValue(t, time, null);
                                }
                                else
                                {
                                    prop.SetValue(t, value, null);
                                }
                            }
                        }
                        else if (fields.Any(f => string.Compare(f.Name, dr.GetName(i), true) == 0))
                        {
                            field = fields.First(f => string.Compare(f.Name, dr.GetName(i), true) == 0);

                            //如果非空，则赋给对象的属性  
                            if (value != DBNull.Value)
                            {
                                if (field.FieldType == typeof(Boolean)) //转换为布尔值
                                {
                                    field.SetValue(t, ValueAsBoolean(value, false));
                                }
                                else if (field.FieldType.IsEnum) //转换为枚举，支持数字和文字
                                {
                                    field.SetValue(t, Enum.Parse(field.FieldType, value.ToString(), true));
                                }
                                else if (field.FieldType.Equals(typeof(DateTime)))
                                {
                                    DateTime time;
                                    TryParseDateTime(value.ToString(), out time);
                                    field.SetValue(t, time);
                                }
                                else
                                {
                                    field.SetValue(t, value);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }

                return t;
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }

        /// <summary>  
        /// 将DataTable的数据转换为目标的实体类集合  
        /// </summary>  
        /// <param name="dt">数据源</param>  
        /// <returns>目标的实体类对象集合</returns>  
        public static List<T> ToList<T>(DataTable dt) where T : new()
        {
            // 定义集合  
            List<T> ts = new List<T>();

            try
            {
                //遍历DataTable中所有的数据行  
                foreach (DataRow dr in dt.Rows)
                {
                    T t = newT<T>(dr, dt.Columns);

                    //对象添加到泛型集合中  
                    ts.Add(t);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return ts;
        }

        /// <summary>  
        /// 将DataTable的数据转换为目标的实体类  
        /// </summary>  
        /// <param name="dt">数据源</param>  
        /// <returns>目标的实体类对象</returns>  
        public static T ToInstance<T>(DataTable dt) where T : new()
        {
            try
            {
                //读取DataTable中的第一行  
                if (dt.Rows.Count > 0)
                {
                    return newT<T>(dt.Rows[0], dt.Columns);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return default(T);
        }

        /// <summary>
        /// 将DataTable的数据转换为目标的实体类
        /// </summary>
        /// <typeparam name="T">目标的实体类型</typeparam>
        /// <param name="dr">数据行</param>
        /// <param name="dc">数据列</param>
        /// <returns>目标的实体类对象</returns>
        private static T newT<T>(DataRow dr, DataColumnCollection dc) where T : new()
        {
            try
            {
                T t = new T();

                // 获得此模型的所有属性  
                PropertyInfo[] properties = t.GetType().GetProperties();
                PropertyInfo prop;

                // 获得此模型的所有字段  
                FieldInfo[] fields = t.GetType().GetFields();
                FieldInfo field;

                for (int i = 0; i < dc.Count; i++)
                {
                    try
                    {
                        //取值  
                        object value = dr[i];

                        if (properties.Any(p => string.Compare(p.Name, dc[i].ColumnName, true) == 0))
                        {
                            //找到字段对应的的属性  
                            prop = properties.First(p => string.Compare(p.Name, dc[i].ColumnName, true) == 0);
                            if (!prop.CanWrite)//该属性不可写，直接跳出  
                            {
                                continue;
                            }

                            //如果非空，则赋给对象的属性  
                            if (value != DBNull.Value)
                            {
                                if (prop.PropertyType == typeof(Boolean)) //转换为布尔值
                                {
                                    prop.SetValue(t, ValueAsBoolean(value, false), null);
                                }
                                else if (prop.PropertyType.IsEnum) //转换为枚举，支持数字和文字
                                {
                                    prop.SetValue(t, Enum.Parse(prop.PropertyType, value.ToString(), true), null);
                                }
                                else if (prop.PropertyType.Equals(typeof(DateTime)))
                                {
                                    DateTime time;
                                    TryParseDateTime(value.ToString(), out time);
                                    prop.SetValue(t, time, null);
                                }
                                else
                                {
                                    prop.SetValue(t, value, null);
                                }
                            }
                        }
                        else if (fields.Any(f => string.Compare(f.Name, dc[i].ColumnName, true) == 0))
                        {
                            field = fields.First(f => string.Compare(f.Name, dc[i].ColumnName, true) == 0);

                            //如果非空，则赋给对象的属性  
                            if (value != DBNull.Value)
                            {
                                if (field.FieldType == typeof(Boolean)) //转换为布尔值
                                {
                                    field.SetValue(t, ValueAsBoolean(value, false));
                                }
                                else if (field.FieldType.IsEnum) //转换为枚举，支持数字和文字
                                {
                                    field.SetValue(t, Enum.Parse(field.FieldType, value.ToString(), true));
                                }
                                else if (field.FieldType.Equals(typeof(DateTime)))
                                {
                                    DateTime time;
                                    TryParseDateTime(value.ToString(), out time);
                                    field.SetValue(t, time);
                                }
                                else
                                {
                                    field.SetValue(t, value);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }

                return t;
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }

        /// <summary>
        /// 将值转化为布尔值
        /// </summary>
        /// <param name="value">需要转换的值</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static bool ValueAsBoolean(object value, bool defaultValue)
        {
            if (value == null || value == DBNull.Value)
            {
                return false;
            }

            //先用默认的规则
            switch (value.ToString().ToLower())
            {
                case "是":
                case "1":
                case "true":
                case "yes":
                case "y":
                case "+":
                    return true;
                case "否":
                case "0":
                case "false":
                case "no":
                case "n":
                case "-":
                    return false;
            }

            //默认的规则不包含则使用系统的规则
            bool i;
            if (bool.TryParse(value.ToString(), out i))
            {
                return i;
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 转换值为枚举类型
        /// </summary>
        /// <param name="enumType"></param>
        /// <param name="enumValue"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static object TryParseEnum(Type enumType, string enumValue, object defaultValue)
        {

            try
            {
                return Enum.Parse(enumType, enumValue, true);
            }
            catch
            {
                return defaultValue;
            }
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertToUpperMd5(string str)
        {
            string cl = str;
            string pwd = "";
            MD5 md5 = MD5.Create(); //实例化一个md5对像
            // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
            // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符
                string p = s[i].ToString("X");
                if (p.Length < 2)
                {
                    p = "0" + p;
                }
                pwd = pwd + p;
            }
            return pwd;
        }

        /// <summary>
        /// base64编码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Base64Encode(string str)
        {
            byte[] input = Encoding.UTF8.GetBytes(str);
            return Convert.ToBase64String(input);
        }

        /// <summary>
        /// base64解码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Base64Decode(string str)
        {
            return Encoding.UTF8.GetString(Convert.FromBase64String(str));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertToLowerMd5(string str)
        {
            string cl = str;
            string pwd = "";
            MD5 md5 = MD5.Create(); //实例化一个md5对像
            // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
            // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符
                string p = s[i].ToString("x");
                if (p.Length < 2)
                {
                    p = "0" + p;
                }
                pwd = pwd + p;
            }
            return pwd;
        }

        /// <summary>
        /// 获得Guid
        /// </summary>
        /// <returns></returns>
        public static string GetGuid()
        {
            return System.Guid.NewGuid().ToString();
        }

        /// <summary>
        /// 生成唯一ID
        /// </summary>
        /// <returns></returns>
        public static long GetGenerateId()
        {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            return BitConverter.ToInt64(buffer, 0);
        }

        /// <summary>
        /// 指定字符串表示形式转换为其等效的 System.DateTime，如返回false，则为无效的字符串。
        /// </summary>
        /// <param name="dateTimeString"></param>
        /// <returns></returns>
        public static bool TryParseDateTime(string dateTimeString, out DateTime dateTime)
        {
            return TryParseDateTime(dateTimeString, new DateTime(1900, 1, 1), out dateTime);
        }

        /// <summary>
        /// 指定字符串表示形式转换为其等效的 System.DateTime，如返回false，则为无效的字符串。
        /// </summary>
        /// <param name="dateTimeString"></param>
        /// <param name="dafaultValue"></param>
        /// <returns></returns>
        public static bool TryParseDateTime(string dateTimeString, DateTime dafaultValue, out DateTime dateTime)
        {
            if (string.IsNullOrEmpty(dateTimeString))
            {
                dateTime = dafaultValue;
                return false;
            }

            string[] formats = {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
                               "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", 
                               "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", 
                               "M/d/yyyy h:mm", "M/d/yyyy h:mm", 
                               "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm",
                               "yyyyMMdd","yyyy-MM-dd","yyyy/MM/dd",
                               "yyyyMMddHHmmss","yyyy-MM-dd HH:mm:ss","yyyyMMddhhmmss",
                               "yyyyMMddHHmmssfff","yyyy-MM-dd HH:mm:ss.fff","yyyyMMddhhmmssfff"};

            if (!DateTime.TryParse(dateTimeString, out dateTime))
            {
                if (!DateTime.TryParseExact(dateTimeString, formats, new System.Globalization.CultureInfo("en-US")
                    , System.Globalization.DateTimeStyles.None, out dateTime))
                {
                    dateTime = dafaultValue;
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 时间戳（格式：yyyyMMddhhmmssSSS）举例：20120428203319002
        /// </summary>
        public static string Timestamp
        {
            get { return DateTime.Now.ToString("yyyyMMddHHmmss"); }
        }

        /// <summary>
        /// 获得HashCode
        /// </summary>
        /// <param name="Timestamp"></param>
        /// <param name="Caller"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public static string GetHashCode(string Timestamp, string Caller, string Key)
        {
            string code = Timestamp + Caller + Key;
            return ConvertToUpperMd5(code);
        }

        /// <summary>
        /// 检测HashCode
        /// </summary>
        /// <param name="Timestamp"></param>
        /// <param name="Caller"></param>
        /// <param name="Key"></param>
        /// <param name="HashCode"></param>
        /// <returns></returns>
        public static bool ChechHashCode(string Timestamp, string Caller, string Key, string HashCode)
        {
            bool result = false;
            string code = Timestamp + Caller + Key;
            if (GetHashCode(Timestamp, Caller, Key) == HashCode)
            {
                result = true;
            }
            return result;
        }

        private static string _defaultPage = string.Empty;
        public static string DefaultPage
        {
            get
            {
                if (string.IsNullOrEmpty(_defaultPage))
                {
                    _defaultPage = ConfigurationManager.AppSettings["DefaultPage"];
                }
                return _defaultPage;
            }
        }


        /// <summary>
        /// 获得cookie
        /// </summary>
        /// <param name="key"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public static string GetCookie(string cookieName)
        {
            if (HttpContext.Current.Request.Cookies[cookieName] == null)
            {
                return string.Empty;
            }

            string val = HttpContext.Current.Request.Cookies[cookieName].Value;
            byte[] output = Convert.FromBase64String(val);
            val = Encoding.UTF8.GetString(output);
            return val;
        }

        /// <summary>
        ///设置cookie
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="value"></param>
        public static void SetCookie(string cookieName, string value)
        {
            if (HttpContext.Current.Request.Cookies[cookieName] == null)
            {
                HttpCookie cookie = new HttpCookie(cookieName);
                HttpContext.Current.Request.Cookies.Add(cookie);
            }

            byte[] output = Encoding.UTF8.GetBytes(value);
            HttpContext.Current.Response.Cookies[cookieName].Value = Convert.ToBase64String(output);
        }

        /// <summary>
        /// 设置cookie在value分钟后过期
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="value"></param>
        public static void SetCookieTimeOut(string cookieName, double value)
        {
            if (HttpContext.Current.Request.Cookies[cookieName] != null)
            {
                HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Now.AddMinutes(value);
            }
        }

        public static void SetSession(string Key, object value)
        {
            System.Web.HttpContext.Current.Session[Key] = value;
        }

        public static object GetSession(string Key)
        {
            if (System.Web.HttpContext.Current.Session != null)
            {
                return System.Web.HttpContext.Current.Session[Key];
            }
            else
            {
                return null;
            }
        }

        public static void RemoveSession(string Key = null)
        {
            if (Key == null)
            {
                System.Web.HttpContext.Current.Session.RemoveAll();
                return;
            }
            System.Web.HttpContext.Current.Session.Remove(Key);
        }

        /// <summary>
        /// 使cookie失效
        /// </summary>
        /// <param name="cookieName"></param>
        public static void DisableCookie(string cookieName)
        {
            if (HttpContext.Current.Request.Cookies[cookieName] != null)
            {
                HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Now;
            }
        }

        public static string ConvertToXmlString<T>(T t) where T : new()
        {
            string xmlString = string.Empty;

            XmlDocument xd = new XmlDocument();
            using (StringWriter sw = new StringWriter())
            {
                XmlSerializer ser = new XmlSerializer(typeof(T));
                ser.Serialize(sw, t);
                xd.LoadXml(sw.ToString());
                XmlElement element = xd.DocumentElement;
                element.RemoveAllAttributes();
                xmlString = element.OuterXml.ToString();
            }

            return xmlString;
        }


        /// <summary>
        /// 将xml字符串转换成相应的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="XmlString"></param>
        /// <returns></returns>
        public static T ConvertToObject<T>(string XmlString) where T : new()
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            object obj = ser.Deserialize(new StringReader(XmlString));
            return (T)obj;
        }

        /// <summary>
        /// unix时间转换为datetime
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <returns></returns>
        public static DateTime UnixTimeToTime(string timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }

        /// <summary>
        /// datetime转换为unixtime
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static int ConvertDateTimeInt(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (int)(time - startTime).TotalSeconds;
        }
    }
}
